#ifndef SESSIONLIST_H
#define SESSIONLIST_H

#include <QWidget>
#include <QScrollArea>  // 滚动区域
#include <QScrollBar>   // 滚动条
#include <QVBoxLayout>
#include <QPushButton>
#include <QLabel>
#include <QStyleOption>
#include <QPainter>

#include "model/data.h"

//----------------------------------------------------------------------------------------------------------------------------------
/// 滚动区域的类
//----------------------------------------------------------------------------------------------------------------------------------

// 不同的元素类型
enum ItemType
{
    SessionItemType,
    FriemdItemType,
    ApplyItemType
};

class SessionList : public QScrollArea
{
    // 一个类想要支持信号槽机制，就需要加上该宏
    Q_OBJECT

public:
    SessionList(QWidget *parent = nullptr);
    // 清空该区域的所有Item
    void clear();
    // 根据类型，添加一个Item--通过type确定类型，不同类型的id有不同的含义
    // sessionItem就是chatsessionId，applyItem和friendItem就是userId
    void addItem(const ItemType itemType, const QString& id, const QIcon& avator, const QString& nickName, const QString& text);
    // 选中某个指定的Item元素
    void clickItem(int index);


private:
    // 存放一条一条的会话--将来往这里放会话，就可以实现滚动效果
    // 相当于SessionList是一个窗口，他内部区域还存放了一个QWidget窗口，
    // 该窗口添加的元素可能会导致比SessionList高很多很多，那么就会触发滚动
    QWidget* container;
};

//----------------------------------------------------------------------------------------------------------------------------------
/// 滚动区域中的元素的类--包含会话元素、好友元素、好友申请元素
//----------------------------------------------------------------------------------------------------------------------------------

class SessionFriendApplyItem : public QWidget
{
    Q_OBJECT

public:
    // owner参数: 对应着sessionList对象的指针。如果把sessionItem对象直接添加到SessionList的布局管理器当中的话， \
    // 是可以直接使用SessionItem的parent相关操作，就能找到sessionList的，不需要额外的owner参数。
    // 但是实际的情况是，需要把sessionItem添加到sessionList的一个container成员中去添加的，也就是说添加到了container的布局管理器当中
    // 那么获取的parent就是container对象，那么不容易直接获取sessionList对象，为了方便item直接使用list的相关操作，所以提供了一个owner参数
    SessionFriendApplyItem(QWidget* owner, const QIcon& avator, const QString& nickName, const QString& text);

    // 确保QWidget子类设置的样式生效--代码具体什么意思，文档没有任何解释
    // Qt底层实现QSS的时候，本质上是通过"画笔"QPainter这一系列的操作，画上去的，对于Qt内置的类，已经在paintEvent中处理好了相关的逻辑了
    // 但是自定义的类来说，就需要手动的来完成上述的"绘制"操作了，也就相当于现用现画
    void paintEvent(QPaintEvent *event) override;
    // 选中某一个元素
    void select();

    // Item被点击之后的逻辑--对于SessionItem来说应该是触发显示对应对话框的操作，FriendItem则是，ApplyItem则是无任何操作，
    virtual void active() = 0;

    // 鼠标点击事件--对于内置的控件有点击信号，我们可以使用信号槽机制，但是对于自定义的控件的话，没有点击信号，所以使用事件机制
    void mousePressEvent(QMouseEvent* event) override;
    // 鼠标进入和移出的颜色变化
    void enterEvent(QEnterEvent* event) override;
    void leaveEvent(QEvent* event) override;

private:
    QWidget* owner;            // 记录的是sessionList对象
    bool isSelected;           // 是否是被选中的状态--选中的话，颜色会有一些区别

protected:
    // 对于会话元素和好友元素都会有一条message分别代表最后一条信息和个性签名，但是好友申请元素的话，是没有这个的，
    // 所以为了方便applyItem可以移除该label，所以把label元素设置为成员变量。
    // 为了让子类能够访问，还要设置为protected类型
    // 也可以在这里不添加，然后在SessionItem和FriendItem里面单独添加
    QLabel* messageLabel;
}; // end SessionFriendApplyItem

//----------------------------------------------------------------------------------------------------------------------------------
/// 会话元素类
//----------------------------------------------------------------------------------------------------------------------------------

class SessionItem : public SessionFriendApplyItem
{
    Q_OBJECT

public:
    SessionItem(QWidget* owner, const QString& chatSessionId, const QIcon& avator, const QString& nickName, const QString& lastMessage);

    // 重写Item被点击之后的逻辑
    virtual void active() override;

private:
    QString chatSessionId;      // 会话ID

};

//----------------------------------------------------------------------------------------------------------------------------------
/// 好友元素类
//----------------------------------------------------------------------------------------------------------------------------------

class FriendItem : public SessionFriendApplyItem
{
    Q_OBJECT

public:
    FriendItem(QWidget* owner, const QString& userId, const QIcon& avator, const QString& nickName, const QString& description);

    // 重写Item被点击之后的逻辑
    virtual void active() override;

private:
    QString userId;     // 好友用户ID
};


//----------------------------------------------------------------------------------------------------------------------------------
/// 好友申请元素类
//----------------------------------------------------------------------------------------------------------------------------------

class ApplyItem : public SessionFriendApplyItem
{
    Q_OBJECT

public:
    ApplyItem(QWidget* owner, const QString& userId, const QIcon& avator, const QString& nickName);

    // 重写Item被点击之后的逻辑
    virtual void active() override;

private:
    QString userId;   // 申请人用户ID
};

#endif // SESSIONLIST_H






